package pl.mdziedzic.unittests.general;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.util.Calendar;

import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import pl.mdziedzic.unittests.Auction;
import pl.mdziedzic.unittests.CreateAuctionRequest;
import pl.mdziedzic.unittests.User;
import pl.mdziedzic.unittests.services.HistoryProvider;
import pl.mdziedzic.unittests.services.MailProvider;
import pl.mdziedzic.unittests.services.RequestContext;

public class AuctionGiven {
	
private Calendar now = Calendar.getInstance();
	
	public void setTime(Calendar time) {
		now.setTimeInMillis(time.getTimeInMillis());
	}
	
	private RequestContext context;
	private Calendar startTime;
	private Calendar endTime;
	private User user;

	public RequestContext requestContext() {
		user = new User("bad.internet");
		
		context = mock(RequestContext.class);
		HistoryProvider historyProvider = mock(HistoryProvider.class);
		MailProvider mailProvider = mock(MailProvider.class);
		
		when(context.getNow()).thenReturn(now);
		
		// przy okazji testu shouldNotCancelActiveAuctionWithOffer
		// zamieniamy odpowiedz thenReturn na thenAnswer ponieawz tak mozemy dynamicznie zwracac rozne mocki
		when(context.getUser()).thenAnswer(new Answer<User>() {

			@Override
			public User answer(InvocationOnMock invocation) throws Throwable {
				return user;
			}

		});
		
		when(context.getHistoryProvider()).thenReturn(historyProvider);
		when(context.getMailProvider()).thenReturn(mailProvider);
		
		startTime = Calendar.getInstance();
		startTime.add(Calendar.DATE, 1);
		
		endTime = (Calendar) startTime.clone();
		endTime.add(Calendar.DATE, 7);
		
		return context;
	}
	
	// metoda dodana przy okazji thenAnswer
	public void setUser(User user) {
		this.user = user;
	}
	
	public CreateAuctionRequest buyNowAuctionRequest() {
		return CreateAuctionRequest.createBuyNowAuction("Joggy Bear", startTime, endTime, 1000);
	}
	
	public Auction buyNowAuctionWithStatusNew() {
		CreateAuctionRequest request = buyNowAuctionRequest();
		return new Auction(context, request);
	}
	
	public Auction buyNowAuctionWithStatusActive() {
		Auction auction = buyNowAuctionWithStatusNew();
		return activate(auction);
	}
	
	public Calendar getNow() {
		return now;
	}
	
	public Calendar auctionStartTimeMovedByDays(Auction auction, int days) {
		Calendar startTime = (Calendar) auction.getStartTime().clone(); // dlaczego robimy .clone() ?
		startTime.add(Calendar.DAY_OF_YEAR, days);
		
		return startTime;
	}

	public Auction buyNowAuctionWithStatusFinished() {
		Auction auction = buyNowAuctionWithStatusActive();
		auction.finish();
		
		return auction;
	}

	public Auction bidAuctionWithStatusNew() {
		CreateAuctionRequest request = CreateAuctionRequest.createBidAuction("Joggy Bear", startTime, endTime, 100);
		return new Auction(context, request);
	}

	public Auction buyNowAuctionWithStatusCancelled() {
		Auction auction = buyNowAuctionWithStatusNew();
		auction.cancel();
		
		return auction;
	}

	public Auction bidAuctionWithStatusActive() { // przy wprowadzaniu tej metody robimy refaktoring do metody activate
		Auction auction = bidAuctionWithStatusNew();
		return activate(auction);
	}
	
	private Auction activate(Auction auction) {
		setTime(auction.getStartTime());
		
		auction.activate();
		
		return auction;
	}

}
